<html>
<head><meta charset="utf-8"><title>transmute · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html">transmute</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="199369147"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199369147" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Brennan Vincent <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199369147">(Jun 01 2020 at 13:33)</a>:</h4>
<p>Hello, the reference doesn't say (as far as I could find) anything about when it is safe to transmute things. The nomicon gives some examples of when it's <em>un</em>safe, but it's not clear whether they're supposed to be exhaustive.</p>
<p>In particular, the nomicon says that transmuting between non-repr(C) types is always UB, but it's not clear whether <code>T&lt;'a&gt;</code> and <code>T&lt;'b&gt;</code> should be considered "different types". It seems transmuting between those must be okay (as long as the lifetimes are actually valid for the objects in question, of course), but I can't find anywhere where this is guaranteed.</p>
<p>It does seem to be allowed by the examples on <a href="https://doc.rust-lang.org/std/mem/fn.transmute.html">https://doc.rust-lang.org/std/mem/fn.transmute.html</a> , but I'm not sure whether that is meant to be considered an authoritative reference.</p>



<a name="199370032"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199370032" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Frank McSherry <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199370032">(Jun 01 2020 at 13:40)</a>:</h4>
<p>To add some color here, we have two methods we'd love to use in order to reduce allocations; I've wanted this plenty of other times in the past too but never asked. Would either of these be deemed "defined behavior"?</p>
<div class="codehilite"><pre><span></span><code><span class="k">fn</span> <span class="nf">safe_transmute1</span><span class="o">&lt;</span><span class="na">&#39;inner</span><span class="p">,</span><span class="w"> </span><span class="na">&#39;outer</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">buffer</span>: <span class="nb">Vec</span><span class="o">&lt;&amp;</span><span class="na">&#39;inner</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Vec</span><span class="o">&lt;&amp;</span><span class="na">&#39;outer</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="na">&#39;outer</span>: <span class="na">&#39;inner</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">T</span>: <span class="na">&#39;outer</span><span class="p">,</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span>::<span class="n">mem</span>::<span class="n">transmute</span><span class="p">(</span><span class="n">buffer</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>


<p>or</p>
<div class="codehilite"><pre><span></span><code><span class="k">fn</span> <span class="nf">safe_transmute2</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">mut</span><span class="w"> </span><span class="n">buffer</span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">std</span>::<span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(),</span><span class="w"> </span><span class="n">std</span>::<span class="n">mem</span>::<span class="n">size_of</span>::<span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">());</span><span class="w"></span>
<span class="w">    </span><span class="n">assert_eq</span><span class="o">!</span><span class="p">(</span><span class="n">std</span>::<span class="n">mem</span>::<span class="n">align_of</span>::<span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(),</span><span class="w"> </span><span class="n">std</span>::<span class="n">mem</span>::<span class="n">align_of</span>::<span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">());</span><span class="w"></span>
<span class="w">    </span><span class="n">buffer</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span>::<span class="n">mem</span>::<span class="n">transmute</span><span class="p">(</span><span class="n">buffer</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>


<p>Clearly the innards of <code>Vec::with_capacity</code> perform some shenanigans, and the goal is to recycle the allocation without actually needing to involve the allocator. The use (for context) is where you have buffers of things with lifetimes, and you want to re-use the buffer across the things with the lifetimes, but are happy to empty it completely each time.</p>
<p>But, don't let these specific questions get in the way of Brennan's question.</p>



<a name="199371918"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199371918" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Steven Fackler <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199371918">(Jun 01 2020 at 13:54)</a>:</h4>
<p>If you manually construct the new vec with Vec::from_raw_parts, that function should be fine, since the requirements there are just that the allocation is appropriately sized and aligned</p>



<a name="199371956"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199371956" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Steven Fackler <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199371956">(Jun 01 2020 at 13:55)</a>:</h4>
<p>a transmute should definitely work, but IMO doing it manually gives you more obvious guarantees</p>



<a name="199375670"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199375670" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Brennan Vincent <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199375670">(Jun 01 2020 at 14:29)</a>:</h4>
<p><span class="user-mention" data-user-id="243558">@Steven Fackler</span> should it be documented/guaranteed somewhere that transmuting <code>T&lt;'a&gt;</code> to <code>T&lt;'b&gt;</code> is always okay as long as the lifetimes are valid?</p>



<a name="199403162"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199403162" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199403162">(Jun 01 2020 at 18:10)</a>:</h4>
<p>it absolutely should be</p>



<a name="199414926"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199414926" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Elichai Turkel <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199414926">(Jun 01 2020 at 19:54)</a>:</h4>
<p>The second one is definetly UB, because Vec&lt;T1&gt; != V&lt;T2&gt;<br>
More concretely, Rust is allowed to change the order of the fields in a struct, so 2 different types even if they look the same might not have the same field order, padding, etc.</p>
<p>About the first I'm not sure if monomorphism produces 2 different types for different lifetimes. But as people already pointed out, <code>to_raw_parts</code> and <code>from_raw_parts</code> are what you're actually looking for.</p>



<a name="199415193"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/199415193" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#199415193">(Jun 01 2020 at 19:57)</a>:</h4>
<p>After borrowck all lifetimes are replaces with <code>ReErased</code>, so the layout must be identical. (by the way this replacement of lifetimes <code>ReErased</code> after borrowck is the reason specialization is unsound, as lifetimes can affect how associated types are resolved and thus replacing them with <code>ReErased</code> can change it compared to what typeck sees)</p>



<a name="200514701"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/200514701" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#200514701">(Jun 11 2020 at 07:58)</a>:</h4>
<p>generally, the answer to "when is transmute guaranteed to work" is "whenever data layout of both types is guaranteed, and matches appropriately". This just shifts the question but data layout is more broadly useful than transmute so I think it helps. :D</p>



<a name="200514756"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/200514756" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#200514756">(Jun 11 2020 at 07:59)</a>:</h4>
<p><a href="https://rust-lang.github.io/unsafe-code-guidelines/layout.html">https://rust-lang.github.io/unsafe-code-guidelines/layout.html</a> is the best docs we have for what is guaranteed there. please note the disclaimers for things that the UCG agreed should be guaranteed but haven't been RFC'd yet.</p>



<a name="200514774"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute/near/200514774" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/transmute.html#200514774">(Jun 11 2020 at 07:59)</a>:</h4>
<p><span class="user-mention silent" data-user-id="232844">Brennan Vincent</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/transmute/near/199375670">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="243558">Steven Fackler</span> should it be documented/guaranteed somewhere that transmuting <code>T&lt;'a&gt;</code> to <code>T&lt;'b&gt;</code> is always okay as long as the lifetimes are valid?</p>
</blockquote>
<p>that is not something that has come up in UCG discussions around guaranteed layout, I think. But it's a good question. Could you open a thread about that in <a href="https://github.com/rust-lang/unsafe-code-guidelines/issues">https://github.com/rust-lang/unsafe-code-guidelines/issues</a> ?</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>